#include <iostream>
#include "soapH.h"
#include "ck.nsmap"
#include <my_global.h>
#include <mysql.h>
#include "socket.h"      // For UDPSocket and SocketException
#include <iostream>               // For cout and cerr
#include <cstdlib>                // For atoi()
//using namespace std;
using namespace std;
#define SERVER		"localhost"
#define USER		"root"
#define PASSWORD	"root"
#define DATABASE 	"bplnms"
#define PORTNUMBER	8000

#include "snmp_pp/snmp_pp.h"
#include <stdlib.h>
#include <stdio.h>

#ifdef SNMP_PP_NAMESPACE
using namespace Snmp_pp;
#endif


/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <netinet/ether.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>

#define PDEBUG(format, args...) fprintf(stderr, "DEBUG:%s:%d " format, __FILE__, __LINE__, ## args) 


enum _param { DEFAULT = 90 };
//enum _param PARAM;

struct param
{
	char* 			iface;
	int 			flags;
	unsigned long	packet_delay;
};

struct interface
{
	int 			index;
	int				mtu;
	int				metric;
	short			flags;
	struct in_addr	ip;
	struct in_addr	netmask;
	struct in_addr	broadcast;
	struct ether_addr	mac;
} interface;

struct network
{
	unsigned long start, end;
} network;

//////////////////////////////////////////////////////////////////////
struct ifreq iface;
struct param param;

void iface_init(int socket, char* name)
{
	PDEBUG("iface_init() started\n");
	memset(&iface, 0, sizeof(struct ifreq));
	strncpy(iface.ifr_name, name, strlen(name));
	if (ioctl(socket, SIOCGIFINDEX, &iface) == -1) 
		interface.index = -1;
	else {
		interface.index = iface.ifr_ifindex;
		if (ioctl(socket, SIOCGIFADDR, &iface) != -1)
			//memcpy(&iface_ip, &(((struct sockaddr_in * )&iface.ifr_addr)->sin_addr), 4);
			interface.ip = ((struct sockaddr_in * )&iface.ifr_addr)->sin_addr;
		if (ioctl(socket, SIOCGIFNETMASK, &iface) != -1)
			//memcpy(&iface_nmask, &(((struct sockaddr_in * )&iface.ifr_netmask)->sin_addr), 4);
			interface.netmask = ((struct sockaddr_in * )&iface.ifr_netmask)->sin_addr;
		if (ioctl(socket, SIOCGIFBRDADDR, &iface) != -1)
			//memcpy(&iface_bcast, &(((struct sockaddr_in * )&iface.ifr_broadaddr)->sin_addr), 4);
			interface.broadcast = ((struct sockaddr_in * )&iface.ifr_broadaddr)->sin_addr;
		if (ioctl(socket, SIOCGIFHWADDR, &iface) != -1)
			memcpy((void*)interface.mac.ether_addr_octet, (void*)&iface.ifr_hwaddr.sa_data, 6);
		if (ioctl(socket, SIOCGIFMTU, &iface) != -1)
			interface.mtu = iface.ifr_mtu;
		if (ioctl(socket, SIOCGIFFLAGS, &iface) != -1)
			interface.flags = iface.ifr_flags;
		if (ioctl(socket, SIOCGIFMETRIC, &iface) != -1)
			interface.metric = iface.ifr_metric; 
	}	
	PDEBUG("iface_init() stopped\n");
}

int inline iface_get_index()
{
	return (interface.index);
}

int inline iface_get_mtu()
{
	return (interface.mtu);
}

int inline iface_get_metric()
{
	return (interface.metric);
}

short inline iface_get_flags()
{
	return (interface.flags);
}

void inline iface_get_ip(struct in_addr *ip)
{
	(*ip) = interface.ip;
}

void inline iface_get_netmask(struct in_addr *netmask)
{
	(*netmask) = interface.netmask;
}

void inline iface_get_broadcast(struct in_addr *broadcast)
{
	(*broadcast) = interface.broadcast;
}

void inline iface_get_mac(struct ether_addr *mac)
{
	(*mac) = interface.mac;
}


void inline net_calc_network(struct in_addr ip, struct in_addr netmask)
{
	network.start = ip.s_addr & netmask.s_addr; /* sitas isvis niekam nereikalingas, reikia sugalvoti kur i kisti */
	network.end = ip.s_addr | (~netmask.s_addr);
}

in_addr_t net_next_ip(struct in_addr curr_ip)
{
	unsigned long curr;
	curr = ntohl(curr_ip.s_addr);
	if (curr + 1 <= ntohl(network.end)) {
		curr++;
		return (htonl(curr));
	} else return (0);
}

void arp_usage(char* pname)
{
	fprintf(stderr, "Cara pakai: %s arp <options>\n"
					"options:\n"
					"-i <if> 	Network interface\n"
					"-t <time> 	Delay between packets\n"
					"-h  		Help\n",
					pname);
	exit(0);
}

void arp_generate_packet(struct in_addr, struct in_addr, struct ether_addr, u_int8_t*);

int arp_init(int argc, char** argv)
{
	PDEBUG("arp_init called\n");
	//gak extern lagi
	//extern struct param param;
	struct in_addr sip, tip, netmask, tmp;
	int sock_fd;
/**
ll = link level
sockaddr_ll is a device independent physical layer address
struct sockaddr_ll {
*	sll_addr	unsigned char[8]	phy layer addr
*	sll_family	unsigned short		AF_PACKET
*	sll_halen	unsigned char		len of addr
**	sll_hatype	unsigned short		header type
**	sll_pkttype	unsigned char		pkt type
				PACKET_{HOST,BROADCAST,MULTICAST,OTHERHOST,OUTGOING}
***	sll_protocol	unsigned short	phy layer proto
};
total 6, ingat unsigned short itu aku jadi ingat:
bitset<numerical_limits<unsigned short>::digits>(245)
pertama mari kenalan dg header <linux/if_ether.h>
sll_protocol adlh standard ethernet protocol type in net order.
header type: sll_hatype adlh arp type yg didefinisikan di <linux/if_arp.h>

utk kirim kita cukup oprek field yg di * PLUS sll_ifindex.
utk terima cukup field yang di **.
utk bind, cukup field *** dan sll_ifindex.

***/
	struct sockaddr_ll saddr_ll;
	socklen_t sa_size = sizeof(struct sockaddr_ll);
	struct ether_addr mac;
	struct ether_arp* arp_header;
	u_int8_t packet[sizeof(struct ether_header) + sizeof(struct ether_arp)];

	if ( (sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP))) == -1 ) {
		PDEBUG("Error: gagal socket().\n");
		fprintf(stderr, "Error: tidak bisa buat socket.\n");
		exit(1);
	}
	if ( fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1 ) {
		PDEBUG("Error: gagal fcntl().\n");
		fprintf(stderr, "Error: tidak bisa set socket ke non-blocking.\n");
		close(sock_fd);
		exit(1);
	}
	iface_init(sock_fd, param.iface);
	if ( (saddr_ll.sll_ifindex = iface_get_index()) == -1 ) {
		fprintf(stderr, "Error: tidak ada divais %s.\n", param.iface);
		close(sock_fd);
		exit(1);
	}
	iface_get_ip(&sip);
	iface_get_netmask(&netmask);
	iface_get_mac(&mac);
	saddr_ll.sll_family = PF_PACKET;
	saddr_ll.sll_halen = ETH_ALEN;
	memset(&saddr_ll.sll_addr, 0, ETH_ALEN);
	net_calc_network(sip, netmask);
	tip.s_addr = sip.s_addr & netmask.s_addr;
	arp_header = (struct ether_arp*)(packet + sizeof(struct ether_header));
	fprintf(stdout, "Discovering network with %s/%s\n\n", inet_ntoa(sip), ether_ntoa(&mac));
	while ( (tip.s_addr = net_next_ip(tip)) != 0 ) {
		memset(packet, 0, sizeof(packet));
		arp_generate_packet(sip, tip, mac, packet);
		sendto(sock_fd, &packet, 42, 0, (struct sockaddr*)& saddr_ll, sizeof(struct sockaddr_ll));
		usleep(param.packet_delay * 100);
		if (recvfrom(sock_fd, &packet, 42, 0, (struct sockaddr*)& saddr_ll, &sa_size) == 42) {
			if (arp_header->arp_op == htons(ARPOP_REPLY)) {
				memcpy((void*)&tmp, (void*)&arp_header->arp_spa, 4);
				fprintf(stdout, "%-15s %s\n", 
					inet_ntoa(tmp), 
					ether_ntoa((struct ether_addr*)&arp_header->arp_sha)
				);
			}
		}
	}
	return 0;
}

void arp_generate_packet(struct in_addr sip, struct in_addr tip, struct ether_addr smac, u_int8_t* packet)
{
	struct ether_header* eth_header;
	struct ether_arp* arp_header;
	eth_header = (struct ether_header*)packet;
	memset((void*)&eth_header->ether_dhost, 0xff, ETH_ALEN);
	memcpy((void*)&eth_header->ether_shost, (void*)&smac.ether_addr_octet, ETH_ALEN);
	eth_header->ether_type = htons(ETHERTYPE_ARP);
	arp_header = (struct ether_arp*)(packet + sizeof(struct ether_header));
	arp_header->arp_hrd = htons(ARPHRD_ETHER);
	arp_header->arp_pro = htons(ETHERTYPE_IP);
	arp_header->arp_hln = ETH_ALEN;
	arp_header->arp_pln = 4;
	arp_header->arp_op = htons(ARPOP_REQUEST);
	memcpy((void*)arp_header->arp_sha, (void*)&smac.ether_addr_octet, ETH_ALEN);
	memcpy((void*)arp_header->arp_spa, (void*)&sip.s_addr, 4);
	memcpy((void*)arp_header->arp_tpa, (void*)&tip.s_addr, 4);
}

int process_options(int argc, char** argv) 
{
	extern char* optarg;
	extern int opterr, optind, optopt;
	int ch;
	optind = 2;
	//param.packet_delay = PARAM.DEFAULT;
	param.packet_delay = DEFAULT;

	while ( (ch = getopt(argc, argv, "i:t:h")) != -1 ) {
		switch(ch) {
		case 'i':
			param.iface = optarg;
			break;
		case 't':
			param.packet_delay = strtol(optarg, (char**)NULL, 10);
			if (param.packet_delay == LONG_MIN || param.packet_delay 
				== LONG_MAX) {
				fprintf(stderr, "Error: delay paket tidak benar, gunakan default = 90s.\n");
				param.packet_delay = DEFAULT;
			}
			break;
		case 'h':
			param.flags |= 0xffffFFFF;
			break;
		default:
			return -1;
			break;
		}
	}
	if (optind - 2 == 0) {
		fprintf(stderr, "Error: argumen kurang dari 2.\n");
		return -1;
	}
	return 0;
}

#ifdef STANDALONE
void usage(char*);
void sighandler(int);

int main(int argc, char** argv)
{
	if (argc < 2)
		usage(argv[0]);

	signal(SIGQUIT, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGINT, sighandler);

	if (process_options(argc, argv) == -1)
		usage(argv[0]);
	if (strncmp(argv[1], "arp", 3) == 0) {
		if ( (param.flags & 0xffffFFFF) == 0xFFFFffff )
			arp_usage(argv[0]);
		return (arp_init(argc, argv));
	}
	else
		usage(argv[0]);

	return 0;
}
#endif

void usage(char* pname)
{
	fprintf(stderr, "Cara pakai: %s <tipe> <options>\n"
					"tipe: arp, wmi, ping, snmp (yang didukung saat ini: arp)\n"
					"options: -h help\n",
					pname);
	exit(0);
}

void sighandler(int type)
{
	exit(1);
}

//void netdisc(int argc, char* argv[])
void netdisc()
{
int argc = 3;
char* argv[] = { "ems", "arp", "-ieth0" };
	if (argc < 2)
		usage(argv[0]);

	signal(SIGQUIT, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGINT, sighandler);

	if (process_options(argc, argv) == -1)
		usage(argv[0]);
	if (strncmp(argv[1], "arp", 3) == 0) {
		if ( (param.flags & 0xffffFFFF) == 0xFFFFffff )
			arp_usage(argv[0]);
		//return (arp_init(argc, argv));
		arp_init(argc, argv);
	}
	else
		usage(argv[0]);
}
 

/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

//int main(int argc, char **argv)
int snmpDiscover(int argc, char **argv)
{
   //---------[ check the arg count ]----------------------------------------
   if ( argc < 2) {
	  cout << "Usage:\n";
	  cout << argv[0] << " BroadcastIpAddress [options]\n";
	  cout << "options: -vN , use SNMP version 1, 2 or 3, default is 1\n";
	  cout << "         -PPort , remote port to use\n";
	  cout << "         -CCommunity_name, specify community default is 'public' \n";
	  cout << "         -rN , retries default is N = 1 retry\n";
	  cout << "         -tN , timeout in hundredths of seconds; default is N = 100\n";
	  return 1;
   }
cout << "argc: " << argc << endl;
cout << "argv1: " << argv[0] << endl;
cout << "argv2: " << argv[1] << endl;
	//string alamat(argv[0]);
   // Set filter for logging
   DefaultLog::log()->set_filter(ERROR_LOG, 7);
   DefaultLog::log()->set_filter(WARNING_LOG, 7);
   DefaultLog::log()->set_filter(EVENT_LOG, 7);
   DefaultLog::log()->set_filter(INFO_LOG, 7);
   DefaultLog::log()->set_filter(DEBUG_LOG, 7);

   Snmp::socket_startup();  // Initialize socket subsystem

   //---------[ make a GenAddress and Oid object to retrieve ]---------------
   UdpAddress address( argv[1]);      // make a SNMP++ Generic address
   if ( !address.valid()) {           // check validity of address
	  cout << "Invalid Address or DNS Name, " << argv[1] << "\n";
	  return 1;
   }
   Oid oid("1.3.6.1.2.1.1.1.0");      // default is sysDescr

   //---------[ determine options to use ]-----------------------------------
   snmp_version version=version1;                  // default is v1
   int retries=1;                                  // default retries is 1
   int timeout=100;                                // default is 1 second
   u_short port=161;                               // default snmp port is 161
   OctetStr community("public");                   // community name

#ifdef _SNMPv3
   v3MP *v3_MP;
#endif

   char *ptr;

   for(int x=1;x<argc;x++) {                           // parse for version
     if ( strstr( argv[x],"-v2")!= 0) {
       version = version2c;
       continue;
     }
     if ( strstr( argv[x],"-r")!= 0) {                 // parse for retries
       ptr = argv[x]; ptr++; ptr++;
       retries = atoi(ptr);
       if (( retries<0)|| (retries>5)) retries=1; 
       continue;
     }
     if ( strstr( argv[x], "-t")!=0) {                 // parse for timeout
       ptr = argv[x]; ptr++; ptr++;
       timeout = atoi( ptr);
       if (( timeout < 100)||( timeout>500)) timeout=100;
       continue;
     }
     if ( strstr( argv[x],"-C")!=0) {
       ptr = argv[x]; ptr++; ptr++;
       community = ptr;
       continue;
     }
     if ( strstr( argv[x],"-P")!=0) {
       ptr = argv[x]; ptr++; ptr++;
       sscanf(ptr, "%hu", &port);
       continue;
     }

#ifdef _SNMPv3
     if ( strstr( argv[x],"-v3")!= 0) {
       version = version3;
       continue;
     }
#endif
  }

   //----------[ create a SNMP++ session ]-----------------------------------
   int status;
   // bind to any port and use IPv6 if needed
   Snmp snmp(status, 0, (address.get_ip_version() == Address::version_ipv6));

   if ( status != SNMP_CLASS_SUCCESS) {
      cout << "SNMP++ Session Create Fail, " << snmp.error_msg(status) << "\n";
      return 1;
   }

   //---------[ init SnmpV3 ]--------------------------------------------
#ifdef _SNMPv3
   // MUST create a dummy v3MP object if _SNMPv3 is enabled!
   int construct_status;
   v3_MP = new v3MP("dummy", 0, construct_status);
   if (construct_status != SNMPv3_MP_OK)
   {
     cout << "Error initializing v3MP: " << construct_status << endl;
     return 1;
   }
#endif

   //--------[ build up SNMP++ object needed ]-------------------------------
   address.set_port(port);

   //-------[ issue the broadcast, blocked mode ]----------------------------
   cout << "SNMP++ broadcast to " << argv[1] << " SNMPV" 
#ifdef _SNMPv3
        << ((version==version3) ? (version) : (version+1))
#else
        << (version+1)
#endif
        << " Retries=" << retries
        << " Timeout=" << timeout * 10 <<"ms";
#ifdef _SNMPv3
   if (version == version3)
     cout << endl;
   else
#endif
     cout << " Community=" << community.get_printable() << endl << flush;

   UdpAddressCollection addresses;

   // do multiple loops as requested from "retries"
   for (int loops=1; loops<= retries + 1; ++loops)
   {
     status = snmp.broadcast_discovery(addresses,
				       (timeout + 99) / 100,
				       address, version, &community);

     if (status == SNMP_CLASS_SUCCESS)
     {
       cout << "SNMP++ Success sending broadcast " << loops << "." << endl;
     }
     else
     {
       cout << "SNMP++ Broadcast Error, " << snmp.error_msg( status)
	    << " (" << status <<")" << endl;
     }
   }

   // filter out duplicates
   UdpAddressCollection filtered_addrs;
   int dummy_pos;

   for (int n=0; n < addresses.size(); ++n)
     if (filtered_addrs.find(addresses[n], dummy_pos) == FALSE)
       filtered_addrs += addresses[n];

   // print out all addressess
   cout << "Found " << filtered_addrs.size() << " agents." << endl;
   for (int m=0; m < filtered_addrs.size(); ++m)
     cout << "Answer received from: " << filtered_addrs[m].get_printable()
	  << endl;

   Snmp::socket_cleanup();  // Shut down socket subsystem
}

// Install as CGI application (ck.cgi).
// Alternatively, run from command line to start a stand-alone server
// $ ck.cgi <port> &
// where <port> is a port number
// Please see the ckclient.cpp file for cookie-related details.
// Remember to change the soap.cookie_domain value to your host





const int ECHOMAX = 255;          // Longest string to echo

//int main(int argc, char *argv[]) {
//int getBPLDeviceName(int argc, char *argv[]) {
int getBPLDeviceName() {

  cout << "masuk bpl device name 1";
  char* argv[] = { "ems", "127.0.0.1", "string utk echo", "8000" };
  int argc = 4;
  if ((argc < 3) || (argc > 4)) {   // Test for correct number of arguments
    cerr << "Usage: " << argv[0] 
         << " <Server> <Echo String> [<Server Port>]\n";
    exit(1);
  }

  string servAddress = argv[1];             // First arg: server address
  char* echoString = argv[2];               // Second arg: string to echo
  int echoStringLen = strlen(echoString);   // Length of string to echo
  if (echoStringLen > ECHOMAX) {    // Check input length
    cerr << "Echo string too long" << endl;
    exit(1);
  }
  unsigned short echoServPort = Socket::resolveService(
    (argc == 4) ? argv[3] : "echo", "udp");

  try {
    UDPSocket sock;
  
    // Send the string to the server
    sock.sendTo(echoString, echoStringLen, servAddress, echoServPort);
  
    // Receive a response
    char echoBuffer[ECHOMAX + 1];       // Buffer for echoed string + \0
    int respStringLen;                  // Length of received response
    if ((respStringLen = sock.recv(echoBuffer, ECHOMAX)) != echoStringLen) {
      cerr << "Unable to receive" << endl;
      exit(1);
    }
  
    echoBuffer[respStringLen] = '\0';             // Terminate the string!
    cout << "Received: " << echoBuffer << endl;   // Print the echoed arg

    // Destructor closes the socket

  } catch (SocketException &e) {
    cerr << e.what() << endl;
    exit(1);
  }
  
  return 0;
}
int main(int argc, char **argv)
{ 
  int m, s;
  struct soap soap;
  char* args[] = { "ems", "127.0.0.1", "-P4700" };
cout << "mau snmpdiscover" << endl;
  	snmpDiscover(3, args);
cout << "sudah snmpdiscover" << endl;

cout << "mau netdisc" << endl;
	netdisc();
cout << "sudah netdisc" << endl;
  cout << "start: getbpldevicename..." << endl;
  getBPLDeviceName();
  cout << "...done" << endl;
  soap_init(&soap);
  soap.cookie_domain = "www.cs.fsu.edu"; // must be the current host name (CGI/standalone)
  //soap.cookie_domain = "linprog1.cs.fsu.edu"; // our stand-alone machine
  soap.cookie_path = "/"; // the path which is used to filter/set cookies with this destination
/*
  if (argc < 2)
  { soap_getenv_cookies(&soap); // CGI app: grab cookies from 'HTTP_COOKIE' env var
    soap_serve(&soap);
  }
  else
  { 
*/
	//m = soap_bind(&soap, NULL, atoi(argv[1]), 100);
	m = soap_bind(&soap, NULL, 8000, 100);
    if (m < 0)
      exit(-1);
    fprintf(stderr, "Socket connection successful %d\n", m);
    for (int i = 1; ; i++)
    { // soap.keep_alive = 1;	// try to keep connection open (see below)
      s = soap_accept(&soap);
      if (s < 0)
        exit(-1);
      fprintf(stderr, "%d: accepted %d IP=%d.%d.%d.%d ... ", i, s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
      soap_serve(&soap); // process RPC skeletons, delete this line and use these 2 lines:
      // while (soap_serve(&soap) == SOAP_OK && soap.keep_alive)	// to enable keep-alive support
        // soap_free_cookies(&soap);
      fprintf(stderr, "served\n");
      soap_end(&soap);		// clean up 
      soap_free_cookies(&soap);	// remove all old cookies from database so no interference when new requests with new cookies arrive
      // Note: threads can have their own cookie DB which they need to cleanup before they terminate
    }
//  } // hilangkan if-else
  return 0;
}


string get_data()
{
	string kembali;

    MYSQL *connect; // Create a pointer to the MySQL instance
    connect=mysql_init(NULL); // Initialise the instance
    /* This If is irrelevant and you don't need to show it. I kept it in for Fault Testing.*/
    if(!connect)    /* If instance didn't initialize say so and exit with fault.*/
    {
        fprintf(stderr,"MySQL Initialization Failed");
        return "ERROR mysql_init";
    }
    /* Now we will actually connect to the specific database.*/

    connect=mysql_real_connect(connect,SERVER,USER,PASSWORD,DATABASE,0,NULL,0);
    /* Following if statements are unneeded too, but it's worth it to show on your
    first app, so that if your database is empty or the query didn't return anything it
    will at least let you know that the connection to the mysql server was established. */

    if(connect){
        printf("Connection Succeeded\n");
    }
    else{
        printf("Connection Failed!\n");
    }
    MYSQL_RES *res_set; /* Create a pointer to recieve the return value.*/
    MYSQL_ROW row;  /* Assign variable for rows. */
    //mysql_query(connect,"SELECT * FROM TABLE");
    mysql_query(connect,"SELECT * FROM device");
    /* Send a query to the database. */
    unsigned int i = 0; /* Create a counter for the rows */

    res_set = mysql_store_result(connect); /* Receive the result and store it in res_set */

    unsigned int numrows = mysql_num_rows(res_set); /* Create the count to print all rows */

    /* This while is to print all rows and not just the first row found, */

    while ((row = mysql_fetch_row(res_set)) != NULL){
        printf("kol1: %s\n",row[i] != NULL ? row[i] : "NULL"); /* Print the row data */
        printf("kol2: %s\n",row[i+1] != NULL ? row[i+1] : "NULL"); /* Print the row data */
        printf("kol3: %s\n",row[i+2] != NULL ? row[i+2] : "NULL"); /* Print the row data */
        printf("kol4: %s\n",row[i+3] != NULL ? row[i+3] : "NULL"); /* Print the row data */
        printf("kol5: %s\n",row[i+4] != NULL ? row[i+4] : "NULL"); /* Print the row data */
        printf("kol2: %s\n",row[i+5] != NULL ? row[i+5] : "NULL"); /* Print the row data */
	//kembali = row[i] + "|" + row[i+1] + "|" + row[i+2] + "|" + row[i+3] + "|" + row[i+4] + "|" + row[i+5];
	kembali.assign(row[i]);
	kembali.append("|");
	kembali.append(row[i+1]);
	kembali.append("|");
	kembali.append(row[i+2]);
	kembali.append("|");
	kembali.append(row[i+3]);
	kembali.append("|");
	kembali.append(row[i+4]);
	kembali.append("|");
	kembali.append(row[i+5]);
    }
    mysql_close(connect);   /* Close and shutdown */
	return kembali;
}

int ck__demo(struct soap *soap, char **r)
{ int n;
  char *s, buf[256];
  // The host and path are set by soap_cookie_domain and soap_cookie_path
  // which MUST be the current domain and path of the CGI app in order
  // to accept cookies intended for this service
  s = soap_cookie_value(soap, "demo", NULL, NULL); // cookie returned by client?
  if (s)
    n = atoi(s)+1; // yes: increment int value as demo example session
  else
    n = 1; // no: return cookie with value 1 to client to start session
  //sprintf(buf, "kembalikan berikut ini %d", n);
  sprintf(buf, "kembalikan berikut ini %s %d", get_data().c_str(), n);
  soap_set_cookie(soap, "demo", buf, NULL, NULL);
  soap_set_cookie_expire(soap, "demo", 5, NULL, NULL); // cookie expires in 5 seconds
  if ((*r = (char*)soap_malloc(soap, strlen(buf)+1)))
    strcpy(*r, buf);
  return SOAP_OK;
}

